﻿using System;
using System.Collections.Generic;
using System.Data.Common;

namespace HobSoft.Utility.SqlGateway
{
    public class DbFactory
    {
        private readonly DbProviderFactory provider;
        private readonly Type providerType;

        private static Dictionary<string, string> providerTransactionTable = new Dictionary<string, string>
        {
            {"System.Data.SqlClient.SqlClientFactory", "System.Data.SqlClient.SqlTransaction"},
            {"System.Data.Odbc.OdbcFactory", "System.Data.Odbc.OdbcTransaction"},
            {"System.Data.OleDb.OleDbFactory", "System.Data.OleDb.OleDbTransaction"},
            {"System.Data.OracleClient.OracleClientFactory", "System.Data.OracleClient.OracleTransaction"}
        };

        private static object _syncLock = new object();

        public DbFactory()
            : this("System.Data.SqlClient")
        {
        }

        public DbFactory(string providerInvariantName)
        {
            provider = DbProviderFactories.GetFactory(providerInvariantName);
            providerType = provider.GetType();
        }

        public static void RegisterTransaction(string factoryName, string transactionName)
        {
            if (providerTransactionTable.ContainsKey(factoryName)) return;
            lock (_syncLock)
            {
                if (!providerTransactionTable.ContainsKey(factoryName))
                    providerTransactionTable.Add(factoryName, transactionName);
            }
        }

        public virtual DbCommand CreateCommand()
        {
            return provider.CreateCommand();
        }

        public virtual DbConnection CreateConnection()
        {
            return provider.CreateConnection();
        }

        public virtual DbParameter CreateParameter()
        {
            return provider.CreateParameter();
        }

        public virtual DbTransaction CreateTransaction()
        {
            if (providerTransactionTable.ContainsKey(providerType.FullName))
            {
                var type = Type.GetType(providerTransactionTable[providerType.FullName]);
                if (type == null) return null;
                return (DbTransaction)Activator.CreateInstance(type);
            }
            return null;
        }
    }
}